﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Globalization;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.ApplicationPages;
using Microsoft.SharePoint.Administration;
using Menu = Microsoft.SharePoint.WebControls.Menu;

namespace Components2.JobManager {

    public class JobEditPage : OperationsPage { //GlobalAdminPageBase, LayoutsPageBase

        protected Control ToolBar;
        protected Menu MenuContentDatabaseSelector;
        protected MenuTemplate MenuContentDatabase;
        protected Button BtnCloneSchedule;
        protected Button BtnCloneOneTime;
        protected Button BtnExecute;
        protected Button BtnDelete;
        protected Label LabelLastRunTime;
        protected Label LabelWebApplication;
        protected Label LabelJobTitle;
        protected Label LabelEnabled;
        protected Label LabelSchedule;
        protected TextBox TxtBeginDay;
        protected DropDownList DDLBeginDayOfWeek;
        protected TextBox TxtBeginHour;
        protected TextBox TxtBeginMinute;
        protected DropDownList DDLBeginMonth;
        protected TextBox TxtBeginSecond;
        protected TextBox TxtEndDay;
        protected DropDownList DDLEndDayOfWeek;
        protected TextBox TxtEndHour;
        protected TextBox TxtEndMinute;
        protected DropDownList DDLEndMonth;
        protected TextBox TxtEndSecond;
        protected TextBox TxtInterval;
        protected DateTimeControl DTCTime;
        protected InputFormSection SectionScheduleType;
        protected InputFormSection SectionScheduleSettings;
        protected PlaceHolder PHRadioSchedule;
        protected PlaceHolder PHRadioOneTime;

        private SPJobDefinition m_jd;
        protected SPJobDefinition CurrentJob {
            get {
                if (this.m_jd == null) {
                    this.m_jd = CurrentJobNoCache;
                    if (this.m_jd == null) {
                        Redirect();
                    }
                }
                return this.m_jd;
            }
        }

        protected SPJobDefinition CurrentJobNoCache {
            get {
                SPFarm local = SPFarm.Local;
                Guid id = new Guid((string)this.ViewState["JobId"]);
                return local.GetObject(id) as SPJobDefinition;
            }
        }

        protected string ScheduleTypeName {
            get {
                string val = Request["JobScheduleTypeParam"];
                if (string.IsNullOrEmpty(val)) {
                    val = CurrentScheduleTypeName;
                }
                return val;
            }
        }

        protected string SelectedContentDB {
            get {
                string val = Request["ContentDB"];
                if (string.IsNullOrEmpty(val)) {
                    foreach (SPContentDatabase cdb in CurrentJob.WebApplication.ContentDatabases) {
                        val = cdb.Name;
                        break;
                    }
                }
                return val;
            }
        }

        protected string CurrentScheduleTypeName {
            get { return CurrentJob.Schedule.GetType().Name; }
        }

        public override string PageToRedirectOnCancel {
            get { return "/_admin/c2/ServiceJobDefinitions.aspx"; }
        }

        protected override string PageToRedirectOnMissingPageParameter {
            get { return PageToRedirectOnCancel; }
        }

        protected override string[] RequiredPageParameters {
            get { return new string[] { "JobId" }; }
        }

        protected void BtnDelete_Click(object sender, EventArgs e) {
            if (base.IsValid) {
                this.CurrentJob.Delete();
                Redirect();
            }
        }

        protected void BtnSaveJob_Click(object sender, EventArgs e) {
            if (base.IsValid) {
                string scheduletype = Request["ScheduleType"];
                switch (scheduletype) {
                    case "SPYearlySchedule":
                        SPYearlySchedule schedule1 = new SPYearlySchedule();
                        CurrentJob.Schedule = schedule1;
                        schedule1.BeginDay = Convert.ToInt32(this.TxtBeginDay.Text);
                        schedule1.BeginHour = Convert.ToInt32(this.TxtBeginHour.Text);
                        schedule1.BeginMinute = Convert.ToInt32(this.TxtBeginMinute.Text);
                        schedule1.BeginMonth = Convert.ToInt32(this.DDLBeginMonth.SelectedValue);
                        schedule1.BeginSecond = Convert.ToInt32(this.TxtBeginSecond.Text);
                        schedule1.EndDay = Convert.ToInt32(this.TxtEndDay.Text);
                        schedule1.EndHour = Convert.ToInt32(this.TxtEndHour.Text);
                        schedule1.EndMinute = Convert.ToInt32(this.TxtEndMinute.Text);
                        schedule1.EndMonth = Convert.ToInt32(this.DDLEndMonth.SelectedValue);
                        schedule1.EndSecond = Convert.ToInt32(this.TxtEndSecond.Text);
                        CurrentJob.Schedule = schedule1;
                        break;
                    case "SPMonthlySchedule":
                        SPMonthlySchedule schedule2 = new SPMonthlySchedule();
                        schedule2.BeginDay = Convert.ToInt32(this.TxtBeginDay.Text);
                        schedule2.BeginHour = Convert.ToInt32(this.TxtBeginHour.Text);
                        schedule2.BeginMinute = Convert.ToInt32(this.TxtBeginMinute.Text);
                        schedule2.BeginSecond = Convert.ToInt32(this.TxtBeginSecond.Text);
                        schedule2.EndDay = Convert.ToInt32(this.TxtEndDay.Text);
                        schedule2.EndHour = Convert.ToInt32(this.TxtEndHour.Text);
                        schedule2.EndMinute = Convert.ToInt32(this.TxtEndMinute.Text);
                        schedule2.EndSecond = Convert.ToInt32(this.TxtEndSecond.Text);
                        CurrentJob.Schedule = schedule2;
                        break;
                    case "SPWeeklySchedule":
                        SPWeeklySchedule schedule3 = new SPWeeklySchedule();
                        schedule3.BeginDayOfWeek = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), this.DDLBeginDayOfWeek.SelectedValue, true);
                        schedule3.BeginHour = Convert.ToInt32(this.TxtBeginHour.Text);
                        schedule3.BeginMinute = Convert.ToInt32(this.TxtBeginMinute.Text);
                        schedule3.BeginSecond = Convert.ToInt32(this.TxtBeginSecond.Text);
                        schedule3.EndDayOfWeek = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), this.DDLEndDayOfWeek.SelectedValue, true);
                        schedule3.EndHour = Convert.ToInt32(this.TxtEndHour.Text);
                        schedule3.EndMinute = Convert.ToInt32(this.TxtEndMinute.Text);
                        schedule3.EndSecond = Convert.ToInt32(this.TxtEndSecond.Text);
                        CurrentJob.Schedule = schedule3;
                        break;
                    case "SPDailySchedule":
                        SPDailySchedule schedule4 = new SPDailySchedule();
                        schedule4.BeginHour = Convert.ToInt32(this.TxtBeginHour.Text);
                        schedule4.BeginMinute = Convert.ToInt32(this.TxtBeginMinute.Text);
                        schedule4.BeginSecond = Convert.ToInt32(this.TxtBeginSecond.Text);
                        schedule4.EndHour = Convert.ToInt32(this.TxtEndHour.Text);
                        schedule4.EndMinute = Convert.ToInt32(this.TxtEndMinute.Text);
                        schedule4.EndSecond = Convert.ToInt32(this.TxtEndSecond.Text);
                        CurrentJob.Schedule = schedule4;
                        break;
                    case "SPHourlySchedule":
                        SPHourlySchedule schedule5 = new SPHourlySchedule();
                        schedule5.BeginMinute = Convert.ToInt32(this.TxtBeginMinute.Text);
                        schedule5.EndMinute = Convert.ToInt32(this.TxtEndMinute.Text);
                        CurrentJob.Schedule = schedule5;
                        break;
                    case "SPMinuteSchedule":
                        SPMinuteSchedule schedule6 = new SPMinuteSchedule();
                        schedule6.BeginSecond = Convert.ToInt32(this.TxtBeginSecond.Text);
                        schedule6.EndSecond = Convert.ToInt32(this.TxtEndSecond.Text);
                        schedule6.Interval = Convert.ToInt32(this.TxtInterval.Text);
                        CurrentJob.Schedule = schedule6;
                        break;
                    case "SPOneTimeSchedule":
                        CurrentJob.Schedule = new SPOneTimeSchedule(DTCTime.SelectedDate);
                        break;
                }
                this.CurrentJob.Update();
                Redirect();
            }
        }

        private void Redirect() {
            SPUtility.Redirect(PageToRedirectOnCancel, SPRedirectFlags.UseSource, this.Context);
        }

        protected void BtnExecute_Click(object sender, EventArgs e) {
            if (base.IsValid) {
                Guid id = Guid.Empty;
                if (CurrentJob.WebApplication != null) {
                    foreach (SPContentDatabase cdb in CurrentJob.WebApplication.ContentDatabases) {
                        if (this.SelectedContentDB == cdb.Name) {
                            id = cdb.Id;
                            break;
                        }
                    }
                }
                using (SPLongOperation operation = new SPLongOperation(this.Page)) {
                    operation.LeadingHTML = this.GetLocString("WrkTask_PreGears");
                    operation.TrailingHTML = string.Format(this.GetLocString("WrkTask_PostGears"), Request.Url);
                    operation.Begin();

                    this.CurrentJob.Execute(id);

                    operation.End(Request.Url.ToString(), SPRedirectFlags.UseSource, this.Context, null);
                }
            }
        }

        protected void BtnCloneOneTime_Click(object sender, EventArgs e) {
            BtnClone_Click(sender, e, true);
        }

        protected void BtnCloneSchedule_Click(object sender, EventArgs e) {
            BtnClone_Click(sender, e, false);
        }

        protected void BtnClone_Click(object sender, EventArgs e, bool onetime) {
            if (base.IsValid) {
                using (SPLongOperation operation = new SPLongOperation(this.Page)) {
                    operation.LeadingHTML = this.GetLocString("WrkTask_PreGears");
                    operation.TrailingHTML = string.Format(this.GetLocString("WrkTask_PostGears"), Request.Url);
                    operation.Begin();

                    this.CurrentJob.CloneFull(onetime);

                    operation.End(Request.Url.ToString(), SPRedirectFlags.UseSource, this.Context, null);
                }
            }
        }

        protected string GetLocString(string strName) {
            return (string)System.Web.HttpContext.GetGlobalResourceObject("dlc", strName);
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);

            if (!Page.IsPostBack) {
                this.LabelJobTitle.Text = SPHttpUtility.NoEncode(this.CurrentJob.Title);
                if (this.CurrentJob.WebApplication != null) {
                    this.LabelWebApplication.Text = SPHttpUtility.NoEncode(this.CurrentJob.WebApplication.Name);
                } else {
                    this.LabelWebApplication.Text = "N/A";
                }
                DateTime lastRunTime = this.CurrentJob.LastRunTime;
                if (DateTime.Compare(lastRunTime, DateTime.MinValue) == 0) {
                    this.LabelLastRunTime.Text = SPHttpUtility.HtmlEncode(base.GetResource("TimerJobs_NA", new object[0]));
                } else {
                    this.LabelLastRunTime.Text = SPHttpUtility.HtmlEncode(lastRunTime.ToString(CultureInfo.CurrentCulture));
                }
                LabelEnabled.Text = (this.CurrentJob.IsDisabled) ? "No" : "Yes";
                if (this.CurrentJob.Schedule is SPOneTimeSchedule) {
                    LabelSchedule.Text = "Run one-time at " + ((SPOneTimeSchedule)this.CurrentJob.Schedule).Time;
                } else {
                    LabelSchedule.Text = this.CurrentJob.Schedule.ToString();
                }

                //note: only bind data if the type viewing, is the same as the saved type
                if (CurrentScheduleTypeName == ScheduleTypeName) {

                    TypeSwitch.Do(CurrentJob.Schedule,
                        TypeSwitch.Case<SPYearlySchedule>(x => {
                            TxtBeginDay.Text = x.BeginDay.ToString();
                            TxtBeginHour.Text = x.BeginHour.ToString();
                            TxtBeginMinute.Text = x.BeginMinute.ToString();
                            DDLBeginMonth.SelectedValue = x.BeginMonth.ToString();
                            TxtBeginSecond.Text = x.BeginSecond.ToString();
                            TxtEndDay.Text = x.EndDay.ToString();
                            TxtEndHour.Text = x.EndHour.ToString();
                            TxtEndMinute.Text = x.EndMinute.ToString();
                            DDLEndMonth.SelectedValue = x.EndMonth.ToString();
                            TxtEndSecond.Text = x.EndSecond.ToString();
                        }),
                        TypeSwitch.Case<SPMonthlySchedule>(x => {
                            TxtBeginDay.Text = x.BeginDay.ToString();
                            TxtBeginHour.Text = x.BeginHour.ToString();
                            TxtBeginMinute.Text = x.BeginMinute.ToString();
                            TxtBeginSecond.Text = x.BeginSecond.ToString();
                            TxtEndDay.Text = x.EndDay.ToString();
                            TxtEndHour.Text = x.EndHour.ToString();
                            TxtEndMinute.Text = x.EndMinute.ToString();
                            TxtEndSecond.Text = x.EndSecond.ToString();
                        }),
                        TypeSwitch.Case<SPWeeklySchedule>(x => {
                            DDLBeginDayOfWeek.SelectedValue = x.BeginDayOfWeek.ToString();
                            TxtBeginHour.Text = x.BeginHour.ToString();
                            TxtBeginMinute.Text = x.BeginMinute.ToString();
                            TxtBeginSecond.Text = x.BeginSecond.ToString();
                            DDLEndDayOfWeek.SelectedValue = x.EndDayOfWeek.ToString();
                            TxtEndHour.Text = x.EndHour.ToString();
                            TxtEndMinute.Text = x.EndMinute.ToString();
                            TxtEndSecond.Text = x.EndSecond.ToString();
                        }),
                        TypeSwitch.Case<SPDailySchedule>(x => {
                            TxtBeginHour.Text = x.BeginHour.ToString();
                            TxtBeginMinute.Text = x.BeginMinute.ToString();
                            TxtBeginSecond.Text = x.BeginSecond.ToString();
                            TxtEndHour.Text = x.EndHour.ToString();
                            TxtEndMinute.Text = x.EndMinute.ToString();
                            TxtEndSecond.Text = x.EndSecond.ToString();
                        }),
                        TypeSwitch.Case<SPHourlySchedule>(x => {
                            TxtBeginMinute.Text = x.BeginMinute.ToString();
                            TxtEndMinute.Text = x.EndMinute.ToString();
                        }),
                        TypeSwitch.Case<SPMinuteSchedule>(x => {
                            TxtBeginSecond.Text = x.BeginSecond.ToString();
                            TxtEndSecond.Text = x.EndSecond.ToString();
                            TxtInterval.Text = x.Interval.ToString();
                        }),
                        TypeSwitch.Case<SPOneTimeSchedule>(x => {
                            DTCTime.SelectedDate = x.Time;
                        }),
                        TypeSwitch.Case<object>(x => {
                            //Response.Write("Unknown type: " + typeof(x));
                            Response.Write("Unknown type: " + x.GetType());
                        }),
                        TypeSwitch.Default(() => Response.Write("Unknown case."))
                    );
                }

                if (CurrentJob.WebApplication != null) {

                    int seq = 100;
                    foreach (SPContentDatabase cdb in CurrentJob.WebApplication.ContentDatabases) {
                        MenuItemTemplate menuitem = new MenuItemTemplate(cdb.Name);
                        menuitem.Title = cdb.Name;
                        menuitem.Text = cdb.Name;
                        //todo: change to guid instead of name
                        menuitem.ClientOnClickScript = "return SelectContentDB('" + cdb.Name + "');";
                        menuitem.MenuGroupId = 100;
                        menuitem.Sequence = seq++;
                        MenuContentDatabase.Controls.Add(menuitem);
                    }
                    if(SelectedContentDB != null) {
                        MenuContentDatabaseSelector.Text = SelectedContentDB;
                    }

                } else {
                    ToolBar.Visible = false;
                }
            }
        }

        public static Control FindControlRecursive(Control root, string id) {
            if (root.ID == id) {
                return root;
            }
            foreach (Control c in root.Controls) {
                Control control = FindControlRecursive(c, id);
                if (control != null) {
                    return control;
                }
            }
            return null;
        }


        protected override void OnPreRender(EventArgs e) {
            base.OnPreRender(e);

            TxtBeginDay.Parent.Parent.Visible = false;
            DDLBeginDayOfWeek.Parent.Parent.Visible = false;
            TxtBeginHour.Parent.Parent.Visible = false;
            TxtBeginMinute.Parent.Parent.Visible = false;
            DDLBeginMonth.Parent.Parent.Visible = false;
            TxtBeginSecond.Parent.Parent.Visible = false;
            TxtEndDay.Parent.Parent.Visible = false;
            DDLEndDayOfWeek.Parent.Parent.Visible = false;
            TxtEndHour.Parent.Parent.Visible = false;
            TxtEndMinute.Parent.Parent.Visible = false;
            DDLEndMonth.Parent.Parent.Visible = false;
            TxtEndSecond.Parent.Parent.Visible = false;
            TxtInterval.Parent.Parent.Visible = false;
            DTCTime.Parent.Parent.Visible = false;
            PHRadioSchedule.Visible = true;
            PHRadioOneTime.Visible = false;

            switch (ScheduleTypeName) {
                case "SPYearlySchedule":
                    TxtBeginDay.Parent.Parent.Visible = true;
                    TxtBeginHour.Parent.Parent.Visible = true;
                    TxtBeginMinute.Parent.Parent.Visible = true;
                    DDLBeginMonth.Parent.Parent.Visible = true;
                    TxtBeginSecond.Parent.Parent.Visible = true;
                    TxtEndDay.Parent.Parent.Visible = true;
                    TxtEndHour.Parent.Parent.Visible = true;
                    TxtEndMinute.Parent.Parent.Visible = true;
                    DDLEndMonth.Parent.Parent.Visible = true;
                    TxtEndSecond.Parent.Parent.Visible = true;
                    break;
                case "SPMonthlySchedule":
                    TxtBeginDay.Parent.Parent.Visible = true;
                    TxtBeginHour.Parent.Parent.Visible = true;
                    TxtBeginMinute.Parent.Parent.Visible = true;
                    TxtBeginSecond.Parent.Parent.Visible = true;
                    TxtEndDay.Parent.Parent.Visible = true;
                    TxtEndHour.Parent.Parent.Visible = true;
                    TxtEndMinute.Parent.Parent.Visible = true;
                    TxtEndSecond.Parent.Parent.Visible = true;
                    break;
                case "SPWeeklySchedule":
                    DDLBeginDayOfWeek.Parent.Parent.Visible = true;
                    TxtBeginHour.Parent.Parent.Visible = true;
                    TxtBeginMinute.Parent.Parent.Visible = true;
                    TxtBeginSecond.Parent.Parent.Visible = true;
                    DDLEndDayOfWeek.Parent.Parent.Visible = true;
                    TxtEndHour.Parent.Parent.Visible = true;
                    TxtEndMinute.Parent.Parent.Visible = true;
                    TxtEndSecond.Parent.Parent.Visible = true;
                    break;
                case "SPDailySchedule":
                    TxtBeginHour.Parent.Parent.Visible = true;
                    TxtBeginMinute.Parent.Parent.Visible = true;
                    TxtBeginSecond.Parent.Parent.Visible = true;
                    TxtEndHour.Parent.Parent.Visible = true;
                    TxtEndMinute.Parent.Parent.Visible = true;
                    TxtEndSecond.Parent.Parent.Visible = true;
                    break;
                case "SPHourlySchedule":
                    TxtBeginMinute.Parent.Parent.Visible = true;
                    TxtEndMinute.Parent.Parent.Visible = true;
                    break;
                case "SPMinuteSchedule":
                    TxtBeginSecond.Parent.Parent.Visible = true;
                    TxtEndSecond.Parent.Parent.Visible = true;
                    TxtInterval.Parent.Parent.Visible = true;
                    break;
                case "SPOneTimeSchedule":
                    DTCTime.Parent.Parent.Visible = true;
                    PHRadioSchedule.Visible = false;
                    PHRadioOneTime.Visible = true;
                    break;
            }

            if (ScheduleTypeName == "SPOneTimeSchedule") {
                BtnCloneSchedule.Visible = false;
            }
            if (CurrentJob.Name.IndexOf(SPJobDefinitionExt.CLONE) != -1) {
                BtnCloneSchedule.Visible = false;
                BtnCloneOneTime.Visible = false;
                BtnExecute.Visible = false;
                SectionScheduleType.Visible = false;
                SectionScheduleSettings.Visible = false;
            } else {
                BtnDelete.Visible = false;
            }

            if (CurrentJob.LockType == SPJobLockType.ContentDatabase) {

            }
        }
    }
}